/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * Prefix.java
 *
 * Created on 11 févr. 2012, 12:50:28
 */
package gov.nist.ssd.swqb.gui.boxes;

import com.hp.hpl.jena.rdf.model.Model;
import gov.nist.ssd.swqb.core.files.PrefixManager;
import gov.nist.ssd.swqb.gui.ErrorDisplayer;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JTable;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;

/**
 *
 * @author benjamin herbomez
 */
public class PrefixBox extends javax.swing.JDialog {

    private Model jenaModel;
    private PrefixManager manager;

    /** Creates new form Prefix */
    public PrefixBox(java.awt.Frame parent, boolean modal) {
        super(parent, modal);
        initComponents();
        init();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();
        jPanel3 = new javax.swing.JPanel();
        saveButton = new javax.swing.JButton();
        cancelButton = new javax.swing.JButton();
        jPanel4 = new javax.swing.JPanel();
        loadButton = new javax.swing.JButton();
        progressBar = new javax.swing.JProgressBar();
        jPanel5 = new javax.swing.JPanel();
        newButton = new javax.swing.JButton();
        jPanel6 = new javax.swing.JPanel();
        newNsTextField = new javax.swing.JTextField();
        newPrefTextField = new javax.swing.JTextField();
        jPanel2 = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        jScrollPane1 = new javax.swing.JScrollPane();
        prefixTable = new javax.swing.JTable();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Delete this row?");
        setAlwaysOnTop(true);
        setBounds(new java.awt.Rectangle(0, 0, 150, 30));
        setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
        setLocationByPlatform(true);
        setMinimumSize(new java.awt.Dimension(500, 200));
        setModalityType(java.awt.Dialog.ModalityType.APPLICATION_MODAL);

        jPanel1.setName("jPanel1"); // NOI18N
        jPanel1.setLayout(new java.awt.BorderLayout());

        jPanel3.setName("jPanel3"); // NOI18N

        saveButton.setText("Save");
        saveButton.setName("saveButton"); // NOI18N
        saveButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveButtonActionPerformed(evt);
            }
        });
        jPanel3.add(saveButton);

        cancelButton.setText("Cancel");
        cancelButton.setName("cancelButton"); // NOI18N
        cancelButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cancelButtonActionPerformed(evt);
            }
        });
        jPanel3.add(cancelButton);

        jPanel1.add(jPanel3, java.awt.BorderLayout.EAST);

        jPanel4.setName("jPanel4"); // NOI18N

        loadButton.setText("Load");
        loadButton.setToolTipText("Load namespace from current dataset");
        loadButton.setName("loadButton"); // NOI18N
        loadButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                loadButtonActionPerformed(evt);
            }
        });
        jPanel4.add(loadButton);

        jPanel1.add(jPanel4, java.awt.BorderLayout.LINE_START);

        progressBar.setIndeterminate(true);
        progressBar.setName("progressBar"); // NOI18N
        progressBar.setString("Prefix loading");
        progressBar.setStringPainted(true);
        jPanel1.add(progressBar, java.awt.BorderLayout.SOUTH);

        jPanel5.setName("jPanel5"); // NOI18N
        jPanel5.setLayout(new java.awt.BorderLayout());

        newButton.setText("Add");
        newButton.setName("newButton"); // NOI18N
        newButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                newButtonActionPerformed(evt);
            }
        });
        jPanel5.add(newButton, java.awt.BorderLayout.EAST);

        jPanel6.setName("jPanel6"); // NOI18N
        jPanel6.setLayout(new java.awt.GridLayout(1, 0));

        newNsTextField.setText("http://");
        newNsTextField.setName("newNsTextField"); // NOI18N
        jPanel6.add(newNsTextField);

        newPrefTextField.setName("newPrefTextField"); // NOI18N
        jPanel6.add(newPrefTextField);

        jPanel5.add(jPanel6, java.awt.BorderLayout.CENTER);

        jPanel1.add(jPanel5, java.awt.BorderLayout.PAGE_START);

        getContentPane().add(jPanel1, java.awt.BorderLayout.SOUTH);

        jPanel2.setName("jPanel2"); // NOI18N

        jLabel1.setFont(new java.awt.Font("Cantarell", 1, 15));
        jLabel1.setText("Choose prefixes");
        jLabel1.setName("jLabel1"); // NOI18N
        jPanel2.add(jLabel1);

        getContentPane().add(jPanel2, java.awt.BorderLayout.NORTH);

        jScrollPane1.setName("jScrollPane1"); // NOI18N

        prefixTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {
                "Namespaces", "Prefixs"
            }
        ) {
            Class[] types = new Class [] {
                java.lang.String.class, java.lang.String.class
            };
            boolean[] canEdit = new boolean [] {
                false, true
            };

            public Class getColumnClass(int columnIndex) {
                return types [columnIndex];
            }

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });
        prefixTable.setName("prefixTable"); // NOI18N
        jScrollPane1.setViewportView(prefixTable);

        getContentPane().add(jScrollPane1, java.awt.BorderLayout.CENTER);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void saveButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveButtonActionPerformed
        DefaultTableModel model = (DefaultTableModel) this.prefixTable.getModel();
        int rowCount = model.getRowCount();
        //prefixTable.getCellEditor().stopCellEditing();
        TableCellEditor cellEditor = prefixTable.getCellEditor();
        if (cellEditor != null) {
            cellEditor.stopCellEditing();
        }
        for (int i = 0; i < rowCount; ++i) {
            String ns = (String) model.getValueAt(i, 0);
            String value = (String) model.getValueAt(i, 1);

            if (!checkPrefix(value)){
                if(value.length() == 0){
                    Object[] list = {"Ignore this value","Make modification","Delete this entry"};
                    int r = errorDisplayer.askForConfirmWarn(
                            "You have an empty prefix for the namespace : "+ns+"\n"
                            + "Do you want to continue (your modification for this namespace will be ignored)", 
                            value,
                            list,
                            0,
                            this.rootPane);
                            
                    if(r == 0)
                        continue;
                    else if(r == 1)
                        return;
                    else{
                        result.put(ns, null);
                        continue;
                    }
                }
                else{
                    errorDisplayer.displayError("You have an error with the prefix \""+value+"\" for the namespace : "+ns);
                    break;
                }
            }
            else
                result.put(ns, value);
        }
        this.dispose();
    }//GEN-LAST:event_saveButtonActionPerformed

    private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
        this.result = null;
        this.dispose();
    }//GEN-LAST:event_cancelButtonActionPerformed

    private void loadButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_loadButtonActionPerformed
        new Thread(
                new Runnable() {

                    @Override
                    public void run() {
                        progressBar.setVisible(true);

                        Map<String, String> newEntries = manager.addFromModel(jenaModel);
                        DefaultTableModel model = (DefaultTableModel) prefixTable.getModel();
                        for (String ns : newEntries.keySet()) {
                            boolean a = true;
                            for (int i = 0; i < model.getRowCount(); ++i) {
                                String v = (String) model.getValueAt(i, 0);
                                if (v.equals(ns)) {
                                    a = false;
                                    break;
                                }
                            }
                            if (a) {
                                model.addRow(new Object[]{ns, newEntries.get(ns)});
                            }
                        }
                        progressBar.setVisible(false);
                    }
                }).start();
    }//GEN-LAST:event_loadButtonActionPerformed

private void newButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newButtonActionPerformed
    String ns = this.newNsTextField.getText().trim();
    String pf = this.newPrefTextField.getText().trim();
    if (this.checkNewEntry()) {
        DefaultTableModel model = (DefaultTableModel) prefixTable.getModel();
        Object o[] = new Object[2];
        o[0] = ns;
        o[1] = pf;
        model.addRow(o);
        this.newNsTextField.setText("http://");
        this.newPrefTextField.setText("");
    }
}//GEN-LAST:event_newButtonActionPerformed

    private boolean startWithDigit(String input) {
        if (input == null || input.length() == 0) {
            return false;
        }
        char c = input.charAt(0);
        return c >= '0' && c <= '9';
    }

    private boolean checkNewEntry() {
        String ns = this.newNsTextField.getText().trim();
        String pf = this.newPrefTextField.getText().trim();
        return ns.length() >= 8 && ns.startsWith("http://")
                && !ns.contains("\t") && !ns.contains("\n") && !ns.contains("\r")
                && checkPrefix(pf);
    }

    private boolean checkPrefix(String pf) {
        return pf.length() >= 1
                && !pf.contains("\t") && !pf.contains("\n") && !pf.contains("\r") && !pf.contains(" ")
                && !startWithDigit(pf);
    }

    public Map<String, String> getPrefix(PrefixManager manager,
            Model jenaModel) {

        this.jenaModel = jenaModel;
        this.manager = manager;

        Set<String> namespaces = manager.getNamespaces();
        Collection<String> prefixs = manager.getPrefixs();

        DefaultTableModel model = (DefaultTableModel) this.prefixTable.getModel();
        Iterator<String> nsIt = namespaces.iterator();
        Iterator<String> pfIt = prefixs.iterator();
        while (nsIt.hasNext() && pfIt.hasNext()) {
            model.addRow(new Object[]{nsIt.next(), pfIt.next()});
        }
        this.progressBar.setVisible(false);
        if (jenaModel == null) {
            this.loadButton.setEnabled(false);
        }
        this.setVisible(true);

        return result;
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton cancelButton;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JPanel jPanel5;
    private javax.swing.JPanel jPanel6;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JButton loadButton;
    private javax.swing.JButton newButton;
    private javax.swing.JTextField newNsTextField;
    private javax.swing.JTextField newPrefTextField;
    private javax.swing.JTable prefixTable;
    private javax.swing.JProgressBar progressBar;
    private javax.swing.JButton saveButton;
    // End of variables declaration//GEN-END:variables
    private Map<String, String> result = new LinkedHashMap<String, String>();
    private ErrorDisplayer errorDisplayer;

    private void init() {
        this.errorDisplayer  = ErrorDisplayer.getInstance();
        newButton.setEnabled(false);
        CaretListener al = new CaretListener() {

            @Override
            public void caretUpdate(CaretEvent e) {
                if (checkNewEntry()) {
                    newButton.setEnabled(true);
                } else {
                    newButton.setEnabled(false);
                }
            }
        };
        this.newNsTextField.addCaretListener(al);
        this.newPrefTextField.addCaretListener(al);

        prefixTable.addMouseListener(new MouseAdapter() {

            @Override
            public void mouseReleased(MouseEvent e) {
                final int r = prefixTable.rowAtPoint(e.getPoint());
                if (r >= 0 && r < prefixTable.getRowCount()) {
                    prefixTable.setRowSelectionInterval(r, r);
                } else {
                    prefixTable.clearSelection();
                }

                int rowindex = prefixTable.getSelectedRow();
                if (rowindex < 0) {
                    return;
                }
                if (e.isPopupTrigger() && e.getComponent() instanceof JTable) {
                    Object[] o = {"Delete this Row"};
                    JPopupMenu popup = new JPopupMenu();
                    
                    JMenuItem it = new JMenuItem("Delete this row");
                    it.addActionListener(new ActionListener() {

                        @Override
                        public void actionPerformed(ActionEvent e) {
                            int v = JOptionPane.showConfirmDialog(rootPane,
                                "Do you want to delete : "+prefixTable.getValueAt(r, 0)+" : "+prefixTable.getValueAt(r, 1),
                                "Delete",
                                JOptionPane.YES_NO_OPTION);
                            if(v == JOptionPane.YES_OPTION){
                                DefaultTableModel model = (DefaultTableModel) prefixTable.getModel();
                                result.put((String)prefixTable.getValueAt(r, 0),null);
                                model.removeRow(r);
                            }
                        }
                    });
                    
                    popup.add(it);
                    popup.show(e.getComponent(), e.getX(), e.getY());
                }
            }
        });
    }
}
